#include "stdafx.h"
#include <wtypes.h>
#include <winbase.h>
#include "TCameraAction.h"
namespace
{
	struct DoAction : public std::unary_function<TAction*, void>
	{
		CWnd *m_pWnd;
		DWORD *m_pTime;
		DoAction(CWnd *pWnd, DWORD *time): m_pWnd(pWnd), m_pTime(time){}
		void operator () (TAction *pAct)
		{
			if (pAct)
			{
				::Sleep(*m_pTime);
				pAct->DoAction();
				m_pWnd->RedrawWindow();
			}
		}
	};
}

void TMoveTo::DoAction()
{
	if (!m_pCamera)
		return;
	m_pCamera->MoveRight((float)(m_ptTo.x - m_ptFrom.x));
	m_pCamera->MoveUp((float)(m_ptFrom.y - m_ptTo.y));
	m_pCamera->MoveForward((float)(m_ptFrom.z - m_ptTo.z));
}

void TRotate::DoAction()
{
	if (!m_pCamera)
		return;
	m_pCamera->RotateWorld((float)m_dRadian, (float)m_vAxis.x, (float)m_vAxis.y, (float)m_vAxis.z);
}

TAction* TActionDeque::ActionFactory(TAction *pAct)
{
	switch (pAct->GetType())
	{
	case TAction::MOVETO:
		return new TMoveTo(*(TMoveTo*)pAct);
		break;
	case TAction::ROTATE:
		return new TRotate(*(TRotate*)pAct);
		break;
	default:
		break;
	}
	return NULL;
}

void TActionDeque::push(TAction *pAct)
{
	m_deque.push_back(ActionFactory(pAct));
}

void TActionDeque::doAction(CWnd *pWnd, DWORD &time)
{
	std::for_each(m_deque.begin(), m_deque.end(), DoAction(pWnd, &time));
}

TActionDeque::~TActionDeque()
{
	KernelUtility::Release_V_ptr<TAction>(m_deque);
}


TActionDeque& TActionDeque::operator = (const TActionDeque &deque)
{
	if (this != &deque)
		m_deque.assign(deque.m_deque.begin(), deque.m_deque.end());
	return *this;
}